/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2011-2020 Rock Mao
* creator : Rock Mao
* created : 2011-6-27   22:29
* filename: LaborD3D11Device.cpp
-----------------------------------------------------------------------------
*/
#include "stdafx.h"
#include "LaborD3D11Device.h"
NAMESPACE_LABOR3D_BEGIN
//---------------------------------------------------------------------
CLD3D11Device::eExceptionsErrorLevel CLD3D11Device::mExceptionsErrorLevel = CLD3D11Device::D3D_NO_EXCEPTION;

//---------------------------------------------------------------------
CLD3D11Device::CLD3D11Device( ID3D11Device * D3D11device ) : m_pD3D11Device(D3D11device)
{
	D3D11device->GetImmediateContext(&m_pImmediateContext);

	ID3D11InfoQueue * pInfoQueue = NULL; 
	HRESULT hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11InfoQueue), (LPVOID*)&pInfoQueue);

	if (SUCCEEDED(hr))
	{
		pInfoQueue->ClearStoredMessages();
		pInfoQueue->ClearRetrievalFilter();
		pInfoQueue->ClearStorageFilter();

		D3D11_INFO_QUEUE_FILTER filter;
		ZeroMemory(&filter, sizeof(D3D11_INFO_QUEUE_FILTER));
		std::vector<D3D11_MESSAGE_SEVERITY> severityList;

		switch(mExceptionsErrorLevel)
		{
		case D3D_NO_EXCEPTION:
			severityList.push_back(D3D11_MESSAGE_SEVERITY_CORRUPTION);
		case D3D_CORRUPTION:
			severityList.push_back(D3D11_MESSAGE_SEVERITY_ERROR);
		case D3D_ERROR:
			severityList.push_back(D3D11_MESSAGE_SEVERITY_WARNING);
		case D3D_WARNING:
		case D3D_INFO:
			severityList.push_back(D3D11_MESSAGE_SEVERITY_INFO);
		default: 
			break;
		}


		if (severityList.size() > 0)
		{
			filter.DenyList.NumSeverities = severityList.size();
			filter.DenyList.pSeverityList = &severityList[0];
		}

		pInfoQueue->AddStorageFilterEntries(&filter);
		pInfoQueue->AddRetrievalFilterEntries(&filter);
	}
}
//---------------------------------------------------------------------
CLD3D11Device::CLD3D11Device() : m_pD3D11Device(0), m_pImmediateContext(0)
{

}

//---------------------------------------------------------------------
CLD3D11Device::~CLD3D11Device()
{

}

//---------------------------------------------------------------------
ID3D11Device * CLD3D11Device::operator=( ID3D11Device * D3D11device )
{
	m_pD3D11Device = D3D11device; 
	if (D3D11device)
	{
		D3D11device->GetImmediateContext(&m_pImmediateContext);
	}
	return m_pD3D11Device;
}
//---------------------------------------------------------------------
const bool CLD3D11Device::isNull()
{
	return m_pD3D11Device == 0;
}
//---------------------------------------------------------------------
const string CLD3D11Device::getErrorDescription(const HRESULT lastResult /* = NO_ERROR */) const
{
	if (!m_pD3D11Device)
	{
		return "NULL device";
	}

	if (D3D_NO_EXCEPTION == mExceptionsErrorLevel)
	{
		return "infoQ exceptions are turned off";
	}

	std::string res;

	switch (lastResult)
	{
	case NO_ERROR:
		break;
	case E_INVALIDARG:
		res = res + "invalid parameters were passed.\n";
		break;
	default:
		assert(false); // unknown HRESULT
	}

	ID3D11InfoQueue * pInfoQueue = NULL; 
	HRESULT hr = m_pD3D11Device->QueryInterface(__uuidof(ID3D11InfoQueue), (LPVOID*)&pInfoQueue);

	if (SUCCEEDED(hr))
	{
		UINT64 numStoredMessages = pInfoQueue->GetNumStoredMessages();
		for (UINT64 i = 0 ; i < numStoredMessages ; i++ )
		{
			// Get the size of the message
			SIZE_T messageLength = 0;
			hr = pInfoQueue->GetMessage(i, NULL, &messageLength);
			// Allocate space and get the message
			D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength);
			hr = pInfoQueue->GetMessage(i, pMessage, &messageLength);
			res = res + pMessage->pDescription + "\n";
			free(pMessage);
		}
	}

	return res;
}
//---------------------------------------------------------------------
void CLD3D11Device::release()
{
	SafeRelease(m_pImmediateContext);
	SafeRelease( m_pD3D11Device );
}
//---------------------------------------------------------------------
ID3D11Device * CLD3D11Device::get()
{
	return m_pD3D11Device;
}
//---------------------------------------------------------------------
void CLD3D11Device::setExceptionsErrorLevel( const eExceptionsErrorLevel exceptionsErrorLevel )
{
	mExceptionsErrorLevel = exceptionsErrorLevel;
}
//---------------------------------------------------------------------
const CLD3D11Device::eExceptionsErrorLevel CLD3D11Device::getExceptionsErrorLevel()
{
	return mExceptionsErrorLevel;
}
//---------------------------------------------------------------------

NAMESPACE_LABOR3D_END